package com.example.flutter_aliyun_identity;

import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Looper;
import org.json.JSONObject;
import com.alipay.face.api.*;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import com.alibaba.fastjson.JSON;
import com.alipay.deviceid.DeviceTokenClient;
import com.alipay.face.ToygerConst;
import com.alipay.face.ToygerPresenter;
import com.alipay.face.api.*;
import com.alipay.face.download.BioResManager;
import com.alipay.face.download.BioRuntimeDependency;
import com.alipay.face.log.RecordLevel;
import com.alipay.face.log.RecordService;
import com.alipay.face.log.ZIMCrashCallback;
import com.alipay.face.network.NetworkPresenter;
import com.alipay.face.network.NetworkStore;
import com.alipay.face.ui.FaceLoadingActivity;
import com.alipay.face.ui.UICustomParams;
import com.alipay.face.ui.ZimActivityLifeCircle;
import com.alipay.zoloz.toyger.ToygerLog;
import com.alipay.zoloz.toyger.face.ToygerFaceService;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;

import java.util.HashMap;
import java.util.Map;

/**
 * AliFaceVerifyPlugin
 */
public class FlutterAliyunIdentityPlugin implements FlutterPlugin, MethodCallHandler {
  /// The MethodChannel that will the communication between Flutter and native Android
  ///
  /// This local reference serves to register the plugin with the Flutter Engine and unregister it
  /// when the Flutter Engine is detached from the Activity
  private Context context;
  private MethodChannel channel;
  private boolean hasInit = false;

  @Override
  public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
    context = binding.getApplicationContext();
    channel = new MethodChannel(binding.getBinaryMessenger(), "flutter_aliyun_identity");
    channel.setMethodCallHandler(this);
  }

  @Override
  public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
    if (!hasInit) {
      MyZIMFacade.install(context);
      hasInit = true;
    }
    if (call.method.equals("getMetaInfos")) {
      result.success(MyZIMFacade.getMetaInfos(context));
    } else if (call.method.equals("verify")) {
      HashMap<String, String> params = new HashMap<>(call.arguments());
      String certifyId = params.get("certifyId");

      MyZIMFacade zimFacade = MyZIMFacade.create(context);
      HashMap<String, String> extParams = new HashMap<>();
      //如需支持活体视频返回，请指定这一项，并在response.videoFilePath中获取视频本地路径。
//        extParams.put(ZIMFacade.ZIM_EXT_PARAMS_KEY_USE_VIDEO, ZIMFacade.ZIM_EXT_PARAMS_VAL_USE_VIDEO_TRUE);
      //如需设置OCR的“下一步”按钮颜色（默认可不设置），请设置此项，如红色 #FF0000。
      extParams.put(MyZIMFacade.ZIM_EXT_PARAMS_KEY_OCR_BOTTOM_BUTTON_COLOR, "#FF0000");
      //如需自定义活体检测页面的进度条颜色（默认可不设置），请设置此项，如红色 #FF0000。
      extParams.put(MyZIMFacade.ZIM_EXT_PARAMS_KEY_FACE_PROGRESS_COLOR, "#FF0000");
      zimFacade.verify(certifyId, true, extParams, new ZIMCallback() {
        @Override
        public boolean response(final ZIMResponse response) {
          HashMap<String, String> mapResult = new HashMap<>();
          mapResult.put("msg", response.msg);
          mapResult.put("code", response.code + "");
          mapResult.put("reason", response.reason);
          result.success(new JSONObject(mapResult).toString());
          return true;
        }
      });
    } else {
      result.notImplemented();
    }
  }

  @Override
  public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
    channel.setMethodCallHandler(null);
  }

  private static class MyZIMFacade {
    public static final String ZIM_EXT_PARAMS_KEY_SCREEN_ORIENTATION = "ext_params_key_screen_orientation";
    public static final String ZIM_EXT_PARAMS_VAL_SCREEN_PORT = "ext_params_val_screen_port";
    public static final String ZIM_EXT_PARAMS_VAL_SCREEN_LAND = "ext_params_val_screen_land";
    public static final String ZIM_EXT_PARAMS_KEY_USE_VIDEO = "ext_params_key_use_video";
    public static final String ZIM_EXT_PARAMS_VAL_USE_VIDEO_TRUE = "true";
    public static final String ZIM_EXT_PARAMS_VAL_USE_VIDEO_FALSE = "false";
    public static final String ZIM_EXT_PARAMS_KEY_OCR_BOTTOM_BUTTON_COLOR = "ext_params_key_ocr_bottom_button_color";
    public static final String ZIM_EXT_PARAMS_KEY_FACE_PROGRESS_COLOR = "ext_params_key_face_progress_color";
    private Context ctx;
    private static long lastCallTime = -1L;
    private ZIMCallback zimCallback = null;
    private static String deviceToken;
    private static MyZIMFacade s_instance;

    protected MyZIMFacade(Context ctx) {
      this.ctx = ctx;
    }

    public static synchronized MyZIMFacade create(Context context) {
      if (context == null) {
        throw new RuntimeException("context Can't be null");
      } else {
        if (null == s_instance) {
          s_instance = new MyZIMFacade(context);
        }

        return s_instance;
      }
    }

    public ZIMSession getSession() {
      String sessionContent = deviceToken;
      int ret = -1;
      if (TextUtils.isEmpty(sessionContent)) {
        RecordService.getInstance().recordEvent(RecordLevel.LOG_ERROR, "deviceTokenGetSession", new String[]{"status", "false", "errCode", String.valueOf(-1)});
      } else {
        ret = 0;
        RecordService.getInstance().recordEvent(RecordLevel.LOG_INFO, "deviceTokenGetSession", new String[]{"status", "true", "session", sessionContent});
      }

      ZIMSession zimSession = new ZIMSession();
      zimSession.code = ret;
      zimSession.session = sessionContent;
      return zimSession;
    }

    public void verify(String zimId, boolean useMsgBox, ZIMCallback callback) {
      this.verify(zimId, useMsgBox, (HashMap) null, callback);
    }

    public void verify(String zimId, boolean useMsgBox, HashMap<String, String> extParams, ZIMCallback callback) {
      if (null == this.ctx) {
        this.sendResponse(ToygerConst.ZcodeConstants.ZCODE_SYSTEM_EXC);
      } else if (System.currentTimeMillis() - lastCallTime >= 2000L) {
        if (ZimActivityLifeCircle.getInstance().hasVerifyActivity()) {
          this.sendResponse(ToygerConst.ZcodeConstants.ZCODE_ZIM_IS_BUSY);
          this.destroy();
        } else {
          lastCallTime = System.currentTimeMillis();
          NetworkPresenter.initNetwork(this.ctx);
          RecordService.getInstance().init(this.ctx, zimId);
          this.zimCallback = callback;
          ZIMSession deviceSession = this.getSession();
          RecordService.getInstance().recordEvent(RecordLevel.LOG_INFO, "verifyGetSession", new String[]{"token", deviceSession.session});
          ToygerPresenter.getInstance().setDeviceToken(deviceSession.session);
          ToygerPresenter.getInstance().setZimId(zimId);
          ToygerPresenter.getInstance().setUseMsgBox(useMsgBox);
          ToygerPresenter.getInstance().setZimRetCallback(new ZIMRetCallback() {
            public void onZimFinish(String errCode) {
              MyZIMFacade.this.sendResponse(errCode);
            }
          });
          String ocrBottomButtonColor;
          if (null != extParams && extParams.containsKey("ext_params_key_use_video")) {
            ocrBottomButtonColor = (String) extParams.get("ext_params_key_use_video");
            if ("true".equalsIgnoreCase(ocrBottomButtonColor)) {
              ToygerPresenter.getInstance().setUseVideo(true);
            }
          }

          if (null != extParams) {
            ocrBottomButtonColor = (String) extParams.get("ext_params_key_ocr_bottom_button_color");
            if (!TextUtils.isEmpty(ocrBottomButtonColor)) {
              UICustomParams.OCR_BOTTOM_COLOR = ocrBottomButtonColor;
            }

            String faceProgressColor = (String) extParams.get("ext_params_key_face_progress_color");
            if (!TextUtils.isEmpty(faceProgressColor)) {
              UICustomParams.FACE_PROGRESS_COLOR = faceProgressColor;
            }
          }

          ocrBottomButtonColor = getMetaInfos(this.ctx);
          Intent intent = new Intent(this.ctx, FaceLoadingActivity.class);
          intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
          intent.putExtra("toyger_meta_info", ocrBottomButtonColor);
          if (null != extParams && extParams.containsKey("ext_params_key_screen_orientation")) {
            intent.putExtra("ext_params_key_screen_orientation", (String) extParams.get("ext_params_key_screen_orientation"));
          }

          this.ctx.startActivity(intent);
        }
      }
    }

    public void destroy() {
      ZimActivityLifeCircle.getInstance().finishActivity();
    }

    public static void install(Context context) {
      if (null != context) {
        String appPkgName = context.getPackageName();
        RecordService.getInstance().init(context, appPkgName);
        initApdid(context);
        ToygerFaceService.preLoad(context);
      }
    }

    private static void initApdid(Context context) {
      deviceToken = DeviceTokenClient.getInstance(context).getTokenResult().apdidToken;
      if (TextUtils.isEmpty(deviceToken)) {
        DeviceTokenClient.getInstance(context).initToken("zorro", "elBwppCSr9nB1LIQ", new DeviceTokenClient.InitResultListener() {
          public void onResult(String token, int errorCode) {
            MyZIMFacade.deviceToken = token;
            ToygerLog.e("deviceToken11:" + MyZIMFacade.deviceToken + (Looper.getMainLooper() == Looper.myLooper()));
            if (0 != errorCode) {
              RecordService.getInstance().recordEvent(RecordLevel.LOG_ERROR, "deviceTokenInit", new String[]{"status", "false", "errCode", String.valueOf(errorCode)});
            } else {
              RecordService.getInstance().recordEvent(RecordLevel.LOG_ERROR, "deviceTokenInit", new String[]{"status", "true"});
            }

          }
        });
      }

    }

    private static ZIMMetaInfo getZimMetaInfo(Context context) {
      return getZimMetaInfo(context, (Map) null);
    }

    private static ZIMMetaInfo getZimMetaInfo(Context context, Map<String, Object> params) {
      AppDataProvider appDataProvider = new AppDataProvider() {
        public String getApdidToken(Context context) {
          return MyZIMFacade.getApDidToken(context);
        }

        public String getDeviceType() {
          return "android";
        }

        public String getDeviceModel() {
          return Build.MODEL;
        }

        public String getAppName(Context context) {
          return context == null ? "" : context.getPackageName();
        }

        public String getAppVersion(Context context) {
          String versionName = "";

          try {
            PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
            versionName = info.versionName;
          } catch (PackageManager.NameNotFoundException var4) {
            ToygerLog.w(var4);
          }

          return versionName;
        }

        public String getOsVersion() {
          return Build.VERSION.RELEASE;
        }
      };
      ZIMMetaInfo zimMetaInfo = new ZIMMetaInfo();
      zimMetaInfo.setApdidToken(appDataProvider.getApdidToken(context));
      zimMetaInfo.setAppName(appDataProvider.getAppName(context));
      zimMetaInfo.setAppVersion(appDataProvider.getAppVersion(context));
      zimMetaInfo.setDeviceModel(appDataProvider.getDeviceModel());
      zimMetaInfo.setDeviceType(appDataProvider.getDeviceType());
      zimMetaInfo.setOsVersion(appDataProvider.getOsVersion());
      zimMetaInfo.setBioMetaInfo("6.2.0:21478612992,0");
      zimMetaInfo.setZimVer("1.0.0");
      zimMetaInfo.setSdkVersion("1.1.0");
      return zimMetaInfo;
    }

    public static String getMetaInfos(Context context) {
      return getMetaInfos(context, (Map) null);
    }

    public static String getMetaInfos(Context context, Map<String, Object> params) {
      return getMetaInfos(context, params, true);
    }

    private static String getMetaInfos(Context context, Map<String, Object> params, boolean needInit) {
      ZIMMetaInfo zimMetaInfo = getZimMetaInfo(context, params);
      String metaInfos = "";

      try {
        metaInfos = JSON.toJSONString(zimMetaInfo);
      } catch (Throwable var6) {
        ToygerLog.e(var6);
      }

      return metaInfos;
    }

    private static String getApDidToken(Context context) {
      if (TextUtils.isEmpty(deviceToken)) {
        deviceToken = DeviceTokenClient.getInstance(context).getTokenResult().apdidToken;
      }

      ToygerLog.e("deviceToken: " + deviceToken);
      return deviceToken;
    }

    private void sendResponse(String errCode) {
      if (TextUtils.isEmpty(errCode)) {
        errCode = ToygerConst.ZcodeConstants.ZCODE_SYSTEM_EXC;
      }

      RecordService.getInstance().flush();
      if (null != this.zimCallback) {
        ZIMResponse zimResponse = new ZIMResponse();
        zimResponse.reason = errCode;
        zimResponse.deviceToken = ToygerPresenter.getInstance().getDeviceToken();
        if (ToygerPresenter.getInstance().getUseVideo()) {
          zimResponse.videoFilePath = ToygerPresenter.getInstance().getVideoFilePath();
        }

        zimResponse.bitmap = ToygerPresenter.getInstance().getReturnBitmapByte();
        if (ToygerPresenter.getInstance().isOcrEnabled()) {
          zimResponse.ocrFrontBitmap = ToygerPresenter.getInstance().getOcrFrontBitmap();
          zimResponse.ocrBackBitmap = ToygerPresenter.getInstance().getOcrBackBitmap();
        }

        if (errCode.equalsIgnoreCase(ToygerConst.ZcodeConstants.ZCODE_NET_VERIFY_SUCCESS)) {
          zimResponse.code = 1000;
        } else if (errCode.startsWith(ToygerConst.ZcodeConstants.ZCODE_VERIFY_FAIL_PREFIX)) {
          String[] errs = errCode.split("_");
          if (2 == errs.length) {
            zimResponse.reason = errs[1];
          }

          zimResponse.code = 2006;
        } else if (!errCode.equalsIgnoreCase(ToygerConst.ZcodeConstants.ZCODE_NET_INIT_ERROR) && !errCode.equalsIgnoreCase(ToygerConst.ZcodeConstants.ZCODE_NET_UPLOAD_IMAGE_ERROR) && !errCode.equalsIgnoreCase(ToygerConst.ZcodeConstants.ZCODE_NET_VERIFY_ERROR) && !errCode.equalsIgnoreCase(ToygerConst.ZcodeConstants.ZCODE_NETWORK_TIMEOUT) && !errCode.equalsIgnoreCase(ToygerConst.ZcodeConstants.ZCODE_NETWORK_ERROR) && !errCode.equalsIgnoreCase(ToygerConst.ZcodeConstants.ZCODE_OSS_TOKEN_INVALID)) {
          if (errCode.equalsIgnoreCase(ToygerConst.ZcodeConstants.ZCODE_USER_BACK)) {
            zimResponse.code = 1003;
          } else if (errCode.equalsIgnoreCase(String.valueOf(2003))) {
            zimResponse.code = 2003;
          } else {
            zimResponse.code = 1001;
          }
        } else {
          zimResponse.code = 2002;
        }

        this.zimCallback.response(zimResponse);
      }

    }

    public static void reportCrash(String content, ZIMCrashCallback zimCrashCallback) {
      RecordService.getInstance().recordEvent(RecordLevel.LOG_INFO, "appCrash", new String[]{"crashInfo", content});
      RecordService.getInstance().reportCrash(zimCrashCallback);
    }

    public static Map getNetStore() {
      return NetworkStore.getInstance().get();
    }

    public void checkDownloadFile(Context context, final ZimDownloadCallback callback) {
      BioResManager.getInstance().reset();
      BioResManager.Callback bioCallBack = new BioResManager.Callback() {
        public void onInitComplete() {
        }

        public void onDownloadStart(String s) {
        }

        public void onDownloadComplete(String s) {
        }

        public void onAllDownloadComplete() {
          BioResManager.getInstance().startLoading();
          if (callback != null) {
            callback.onAllDownloadComplete();
          }

        }

        public void onError(int i, int i1, String s) {
          if (callback != null) {
            callback.onError(i, i1, s);
          }

        }
      };
      BioRuntimeDependency dependency = BioResManager.getBioRuntimeDependency(context);
      if (dependency != null) {
        int status = BioResManager.getInstance().init(context, dependency, bioCallBack);
        if (status != 2) {
          if (status == 5) {
            callback.onAllDownloadComplete();
          } else {
            if (status == 1) {
              BioResManager.getInstance().startDownload();
            } else {
              callback.onAllDownloadComplete();
            }

          }
        }
      }
    }
  }
}
